package vg.modules.search.components.firstPanel;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import vg.modules.search.DataBaseWorker4Search;
import vg.modules.search.FBSearchPanel;
import vg.services.data_base_manager.data.graph.Graph;
import vg.services.graph_view_manager.interfaces.graph_view.AGraphView;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphRenderer;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.actions.DefaultActionAdapter;
import vg.services.plugin_manager.realization.PluginParameter;
import vg.services.user_interface_manager.additional_swing_components.Locker;
import vg.services.user_interface_manager.additional_swing_components.conditionPanel.ConditionalPanel;

/**
 * This class realizes first panel for search panel.
 * @author tzolotuhin
 */
public class FirstPanel {
	// Data
	private final PluginParameter parameter;
	private FBSearchPanel fbSearchPanel;
	
	private Set<Integer> vertex_ids; // vertex ids for searching
	private Set<String> vertex_attributes;
	private int graph_model_id = -1;
	private AGraphView last_view;
	private AGraphView current_view;
	private Graph current_subgraph;
	
	// Swing components
	private final JPanel view;
	private final Locker locker;
	private final ConditionalPanel conditionalPanel;
	private final JLabel chooseGraphLabel;
	private final GraphComboBox graphComboBox;
	
	// Mutex
	private final Object general_mutex = new Object();
	
	/**
	 * Constructor.
	 * @param parameter - connection with model and user interface.
	 * @param fbSearchPanel - feedback with search panel.
	 */
	public FirstPanel(PluginParameter parameter, FBSearchPanel fbSearchPanel) {
		this.parameter = parameter;
		this.fbSearchPanel = fbSearchPanel;
		// create swing components
		this.view = new JPanel(new GridBagLayout());
		this.conditionalPanel = new ConditionalPanel();
		this.locker = new Locker("Graph locker");
		locker.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				synchronized (general_mutex) {
					change_view();
				}
			}
		});
		
		this.chooseGraphLabel = new JLabel("Place :");
		this.graphComboBox = new GraphComboBox();
		this.graphComboBox.addItem(GraphComboBox.DEF_VIEW, null, "Selection subgraph");
		this.graphComboBox.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				synchronized (general_mutex) {
					// automatically unlock view
					locker.setStation(Locker.DEF_UNLOCK);
					change_view();
				}
			}
		});
		// build view
		GridBagConstraints gbc = new GridBagConstraints(0,0,  1,1,  0,0,  GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 10, 5, 0),  0,0);
		view.add(chooseGraphLabel, gbc);
		// add graph combo box
		gbc = new GridBagConstraints(1,0,  1,1,  1,0,  GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 10),  0,0);
		view.add(graphComboBox.getView(), gbc);
		// add locker
		gbc = new GridBagConstraints(0,1,  2,1,  1,0,  GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 10),  0,0);
		view.add(locker.getView(), gbc);
		// add split pane between conditional panel and additional panel
		gbc = new GridBagConstraints(0,2,  2,1,  1,1,  GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5),  0,0);
		view.add(conditionalPanel.getView(), gbc);
	}
	/**
	 * This method adds new graph (name and id).
	 * @param id - id of graph in main storage.
	 * @param name - name of graph (only for user).
	 */
	public void addGraph(int id, String name) {
		synchronized (general_mutex) {
			if(id >= 0 && name != null) {
				graphComboBox.addItem(GraphComboBox.DEF_GRAPH, id, name);
			}
		}
	}
	
	public void reset() {
		synchronized (general_mutex) {
			while(graphComboBox.getItemCount() > 1) {
				graphComboBox.removeItem(1);
			}
		}
	}

	public void setCurrentView(AGraphView currentView) {
		synchronized (general_mutex) {
			last_view = currentView;
			change_view();
		}
	}
	/**
	 * This method updates user interface.
	 */
	public void updateUITheme() {
		synchronized (general_mutex) {
			SwingUtilities.updateComponentTreeUI(view);
			conditionalPanel.updateUITheme();
		}
	}

	public Set<String> getVertexAttributes() {
		synchronized (general_mutex) {
			return vertex_attributes;
		}
	}
	public JPanel getView() {
		synchronized (general_mutex) {
			return view;
		}
	}
	/**
	 * This method builds tree.
	 */
	public FirstPanelData getFirstPanelData() {
		synchronized (general_mutex) {
			// automatically lock view
			locker.setStation(Locker.DEF_LOCK);
			
			FirstPanelData data = new FirstPanelData();
			
			data.conditionTokens = conditionalPanel.getConditionTokens();
            data.vertexIds = vertex_ids;
			data.attributes = new HashSet<String>(conditionalPanel.getStringAttributeSet());
			data.graphModelId = graph_model_id;
			
			return data;
		}
	}
//=============================================================================
//-----------------PRIVATE METHODS---------------------------------------------
	private void change_view() {
		if(locker.getStation() != Locker.DEF_UNLOCK) return;
		
		vertex_ids = null;
		
		int type = graphComboBox.getSelectedType();
		if(type == GraphComboBox.DEF_VIEW) {
			current_view = last_view;
			
			if(current_view != null) {
                current_view.addAction(new DefaultActionAdapter("search action") {
                    @Override
                    public void finishAction(IGraphRenderer graphRenderer) {
                        Set<String> stringAttributeSet = DataBaseWorker4Search.getStringAttributeSet4Vertices(vertex_ids, parameter.graphDataBase);
                        Set<String> realAttributeSet = DataBaseWorker4Search.getRealAttributeSet4Vertices(vertex_ids, parameter.graphDataBase);
                        conditionalPanel.setAttributeSets(stringAttributeSet, realAttributeSet);
                    }

                    @Override
                    public void action(final IGraphRenderer graphRenderer) {
                        current_subgraph = graphRenderer.getOriginalSelectedSubGraph();

                        if(current_subgraph == null)
                            current_subgraph = graphRenderer.getOriginGraph();

                        if(current_subgraph != null) {
                            vertex_ids = parameter.graphDataBase.getAllVertexIds4Graph(current_subgraph);
                            graph_model_id = graphRenderer.getDataBaseGraphModelId();
                        }
                    }
                });
            }
		} else {
			graph_model_id = (Integer)this.graphComboBox.getSelectedObject();
			vertex_ids = parameter.graphDataBase.getAllVertexIds4GraphModel(graph_model_id);

            Set<String> stringAttributeSet = DataBaseWorker4Search.getStringAttributeSet4Vertices(vertex_ids, parameter.graphDataBase);
            Set<String> realAttributeSet = DataBaseWorker4Search.getRealAttributeSet4Vertices(vertex_ids, parameter.graphDataBase);
            conditionalPanel.setAttributeSets(stringAttributeSet, realAttributeSet);
        }
	}
}
